package server;

import container.Context;
import container.Host;
import container.Mapper;
import container.Server;

import java.io.InputStream;
import java.net.Socket;
import java.util.Map;
import java.util.Objects;

public class RequestProcessor extends Thread {

    private Socket socket;
    private Server server;
    private String path;

    public RequestProcessor(Socket socket, Server server, String path) {
        this.socket = socket;
        this.server = server;
        this.path = path;
    }

    @Override
    public void run() {
        try{
            InputStream inputStream = socket.getInputStream();

            // 封装Request对象和Response对象
            Request request = new Request(inputStream);
            Response response = new Response(socket.getOutputStream());
            HttpServlet httpServlet = findHttpServlet(request);
            // 静态资源处理
            if(httpServlet == null) {
                Context context = findStatic(request);
                if(Objects.nonNull(context)){
                    String url = request.getUrl();
                    String[] urlPattern = url.split("/");
                    String contextName = urlPattern[1];
                    String realPath = path+"/"+contextName+"/target/classes/"+ urlPattern[2];
                    response.outputWebappHtml(realPath);
                }else{
                    response.outputLocalHtml(request.getUrl());
                }

            }else{
                // 动态资源servlet请求
                httpServlet.service(request,response);
            }

            socket.close();

        }catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 根据请求信息找到对应业务 Servlet
     * <pre>
     *  GET web-greet/greet HTTP/1.1
     *  Host: suremotoo.com
     * </pre>
     *
     * @param request
     * @return 具体要执行的 servlet
     */
    private HttpServlet findHttpServlet(Request request) {
        HttpServlet businessServlet = null;
        Map<String, Mapper> serviceMap = server.getServiceMap();
        for (String key : serviceMap.keySet()) {
            String hostName = request.getHost();
            Map<String, Host> hostMap = serviceMap.get(key).getHostMap();
            Host host = hostMap.get(hostName+":"+request.getPort());
            if (host != null) {
                Map<String, Context> contextMap = host.getContextMap();
                // 处理 url
                // eg: web-greet/greet
                String url = request.getUrl();
                String[] urlPattern = url.split("/");
                String contextName = urlPattern[1];
                String servletStr = "/";
                if (urlPattern.length > 2) {
                    servletStr += urlPattern[2];
                }
                // 获取上下文
                Context context = contextMap.get(contextName);
                if (context != null) {
                    Map<String, HttpServlet> servletMap = context.getServletMap();
                    businessServlet = servletMap.get(servletStr);
                }
            }
        }
        return businessServlet;
    }

    private Context findStatic(Request request) {
        Map<String, Mapper> serviceMap = server.getServiceMap();
        Context context = null;
        for (String key : serviceMap.keySet()) {
            String hostName = request.getHost();
            Map<String, Host> hostMap = serviceMap.get(key).getHostMap();
            Host host = hostMap.get(hostName+":"+request.getPort());
            if (host != null) {
                Map<String, Context> contextMap = host.getContextMap();
                // 处理 url
                // eg: web-greet/greet
                String url = request.getUrl();
                String[] urlPattern = url.split("/");
                String contextName = urlPattern[1];
                String servletStr = "/";
                if (urlPattern.length > 2) {
                    servletStr += urlPattern[2];
                }
                // 获取上下文
                context = contextMap.get(contextName);
                break;
            }
        }
        return context;
    }
}
